package com.haiertvbic.tvwa.network;

import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.xmlpull.v1.XmlPullParser;

import android.content.Context;
import android.database.Cursor;
import android.util.Xml;

import com.haiertvbic.tvwa.db.DbAdapter;
import com.haiertvbic.tvwa.db.InitAppDataBase;
import com.haiertvbic.tvwa.model.ProgramBean;
import com.haiertvbic.tvwa.model.ProgramItemBean;
import com.haiertvbic.tvwa.util.Constant;
import com.haiertvbic.tvwa.util.SLog;

/**
 * @author sun
 * 
 */
public class EPGWeb {
	private static final String TAG = "EPGWeb";
	private static String url = Constant.DEFAULT_URL;
	private static ArrayList<ProgramBean> programFront;
	private static int week;
	private static boolean readfromnet = true; //如果为真删除数据库中的节目
	private static boolean readstate = false;
	/**
	 * 获取指定频道下的节目列表,于2012-9-29日做了节目属性的过滤，用户只能看到过滤后的
	 * 
	 * @param context
	 *            调用此方法的上下文
	 * @param channel_id
	 *            为int值得频道编号
	 * @return 返回一个台的所有节目,如果得不到数据就告知界面无法节目
	 * @throws Exception
	 */
	public static ArrayList<ProgramBean> getProgramList(Context context,
			int channel_id) {
		// http://test.haieross.com/sscepg/haiersscepg?serviceno=4040&serviceauth=服务授权码&sid=随机会话编号&devmac=md5mac&devtype=设备类型号&epgflag=5&ctype=（1：央视，2：卫视，3：其他）&cid=频道id
		Map<String, String> parmas = new HashMap<String, String>();
		// 频道号
		parmas.put("serviceno", "4040");
		parmas.put("serviceauth", "haiertv");
		parmas.put("sid", "123456");
		parmas.put("devmac", "md5mac");
		parmas.put("devtype", "DC18F0M0200A");
		parmas.put("epgflag", "5");
		parmas.put("ctype", 1 + "");
		parmas.put("cid", channel_id + "");
		// 初始化DB
		InitAppDataBase initAppDataBase = new InitAppDataBase();
		if (!initAppDataBase.isDBExist(context)) {
			SLog.d(TAG, "initAppDataBase-----数据库不存在---copyDBFile");
			initAppDataBase.copyDBFile(context);
		} else {
			SLog.d(TAG, "initAppDataBase-----数据库已存在");
		}

		// 只获取当天的节目去掉其他周
		Calendar c = Calendar.getInstance();
		// 得到当前是周几
		week = c.getTime().getDay();
		if (week == 0) {
			week = 7;
		}
		SLog.d(TAG, "当前系统的周数=========" + week);

		ArrayList<ProgramBean> dbcaches = new ArrayList<ProgramBean>();
		dbcaches = getProgramsByChannelId(context, channel_id + "");
		SLog.d(TAG, "从数据库获取指定频道的节目长度========" + dbcaches.size());
		ArrayList<ProgramBean> dbcaches_time = new ArrayList<ProgramBean>();
		dbcaches_time = programTimeFilters(dbcaches);
		
		if (dbcaches != null && dbcaches.size() > 0 && dbcaches_time.size() > 0) {
			SLog.d(TAG, "从数据库得倒节目数据");
			// 为减少数据库体积删除当前日期以前的
			
			for (int i = 0; i < dbcaches.size(); i++) {
				// 节目的周数
				int pro_week = dbcaches.get(i).getPweekday();
				if (week > pro_week && readfromnet) {
					// 删除
					DbAdapter.getInstance(context).deletePrograms(pro_week);
					SLog.d(TAG, "删除了" + i + "条数据");
				}
			}
			// 返回按时间过滤的数据
			return dbcaches_time;
		} else {
			return getformNET(context, channel_id, parmas);
		}
	}

	/**
	 * 按节目查找其他播放频道及时间、集数等
	 * 
	 * @param context
	 *            调用此方法的上下文
	 * @param pid
	 *            节目的唯一标识, test 125,73085，181
	 * @param code
	 *            地区的代码 test1
	 * @return ArrayList<ProgramBean> 返回一个节目在其他台播放情况，如果没有数据就告知界面无法获取数据
	 * @throws Exception
	 */
	public static ArrayList<ProgramBean> getSituation(Context context, int pid,
			String code) throws Exception {
		// http://test.haieross.com/sscepg/haiersscepg?serviceno=4040&serviceauth=服务授权码&sid=随机会话编号&devmac=md5mac&devtype=设备类型号&searchtype=4&fid=节目id&locid=城市id
		Map<String, String> parmas = new HashMap<String, String>();

		parmas.put("serviceno", "4040");
		parmas.put("serviceauth", "haiertv");
		parmas.put("sid", "123456");
		parmas.put("devmac", "md5mac");
		parmas.put("devtype", "DC18F0M0200A");
		parmas.put("searchtype", "4");
		parmas.put("fid", pid + "");// 125,73085
		parmas.put("locid", code);// 1
		SLog.d(TAG, "带过来的本地码是=========="+code);

		// 初始化DB
		InitAppDataBase initAppDataBase = new InitAppDataBase();
		if (!initAppDataBase.isDBExist(context)) {
			SLog.d(TAG, "initAppDataBase-----数据库不存在---copyDBFile");
			initAppDataBase.copyDBFile(context);
		} else {
			SLog.d(TAG, "initAppDataBase-----数据库已存在");
		}

		// 只获取当天的节目去掉其他周
		Calendar c = Calendar.getInstance();
		// 得到当前是周几
		week = c.getTime().getDay();
		if (week == 0) {
			week = 7;
		}
		SLog.d(TAG, "当前系统的周数=========" + week);

		// 根据节目唯一标志从数据库得倒节目
		ArrayList<ProgramBean> dbcaches = new ArrayList<ProgramBean>();
		dbcaches = getProgramsByPid(context, pid + "");
		SLog.d(TAG, "从数据库获取指定频道的节目长度========" + dbcaches.size());
		ArrayList<ProgramBean> dbcaches_time = new ArrayList<ProgramBean>();
		dbcaches_time = programTimeFilters(dbcaches);
		
		if (dbcaches != null && dbcaches.size() > 0 &&  dbcaches_time.size() > 0) {
			SLog.d(TAG, "从数据库得倒节目数据");
			// 为减少数据库体积删除当前日期以前的
			for (int i = 0; i < dbcaches.size(); i++) {
				// 节目的周数
				int pro_week = dbcaches.get(i).getPweekday();
				if (week > pro_week && readfromnet) {
					// 删除
					DbAdapter.getInstance(context).deletePrograms(pro_week);
					SLog.d(TAG, "删除了" + i + "条数据");
				}
			}
			// 返回按时间过滤的数据
			return dbcaches_time;
		} else {
			return getformNET(context, pid, parmas);
		}
	}

	/**
	 * 得倒节目的类型，这段程序由其他程序或代码段开启（比如广播），测试时可直接调用
	 * 
	 * @return ItemProgramBean类型集合，
	 */
	public static ArrayList<ProgramItemBean> getProgramItem(Context context) {
		// http://test.haieross.com/sscepg/haiersscepg?serviceno=4040&serviceauth=服务授权码&sid=随机会话编号&devmac=md5mac&devtype=设备类型号&searchtype=12
		Map<String, String> parmas = new HashMap<String, String>();

		parmas.put("serviceno", "4040");
		parmas.put("serviceauth", "haiertv");
		parmas.put("sid", "123456");
		parmas.put("devmac", "md5mac");
		parmas.put("devtype", "DC18F0M0200A");
		parmas.put("searchtype", "12");

		WebData cloudData = new WebData();
		InputStream result = null;

		// 初始化DB
		InitAppDataBase initAppDataBase = new InitAppDataBase();
		if (!initAppDataBase.isDBExist(context)) {
			SLog.d(TAG, "initAppDataBase-----数据库不存在---copyDBFile");
			initAppDataBase.copyDBFile(context);
		} else {
			SLog.d(TAG, "initAppDataBase-----数据库已存在");
		}

		// 从缓存里那获得到的数据方法
		ArrayList<ProgramItemBean> items = new ArrayList<ProgramItemBean>();
		items = getItems(context);
		if (items != null && items.size() > 0) {
			// 从数据库中取所有节目分类
			return items;
		} else {
			SLog.d(TAG, "从网络获节目分类数据!!");
			result = cloudData.PostDataStream(url, parmas);
			if (result != null) {
				SLog.d(TAG, "================");
				// 解析后的分类数据
				items = paserProgramItem(result);
				SLog.d(TAG, "解析后的分类长度：" + items.size());

				// 将得倒的节目数据存到数据库
				for (int i = 0; i < items.size(); i++) {
					boolean b = DbAdapter.getInstance(context).addItem(
							items.get(i));
					if (b) {
						SLog.i(TAG,
								"第" + i + "个分类数据成功存入数据库,节目分类总数为："
										+ items.size());
					} else {
						SLog.i(TAG,
								"第" + i + "个分类没有成功存入数据库,节目分类总数为："
										+ items.size());
					}
				}
				SLog.i(TAG, "=================================存到db中完成");

			}
			return items;
		}
	}

	private static ArrayList<ProgramItemBean> getItems(Context context) {
		SLog.i(TAG, "从本地取节目分类数据--------------------------");
		ArrayList<ProgramItemBean> items = new ArrayList<ProgramItemBean>();
		DbAdapter dbAdapter = DbAdapter.getInstance(context);
		Cursor cursor = dbAdapter.findAllItem();
		ProgramItemBean item = null;
		while (cursor.moveToNext()) {
			item = new ProgramItemBean();
			item.setNode(cursor.getInt(cursor
					.getColumnIndex(DbAdapter.ITEM_NODE)));
			item.setName(cursor.getString(cursor
					.getColumnIndex(DbAdapter.ITEM_NAME)));
			item.setPnode(cursor.getInt(cursor
					.getColumnIndex(DbAdapter.ITEM_PNODE)));
			items.add(item);
		}
		cursor.close();
		return items;
	}

	/**
	 * 从网络获取数据，并将其存储在本地数据库
	 * 
	 * @param context
	 * @param channel_id
	 * @param parmas
	 * @return
	 */
	private static ArrayList<ProgramBean> getformNET(final Context context,
			int channel_id, Map<String, String> parmas) {

		WebData cloudData = new WebData();
		InputStream result = null;

		SLog.d(TAG, "httpurl===" + url);
		if (cloudData.getNetworkInfo(context)) {
			SLog.d(TAG, "从网络获取节目数据!!");
			result = cloudData.PostDataStream(url, parmas);
		}
		ArrayList<ProgramBean> programs = new ArrayList<ProgramBean>();
		if (result != null) {
			programFront = paserProgram(result);
			readstate = true;
			// 存储到本地数据库中是按属性过滤后的值
			programFront = programAttriFilters(context, programFront);
			// programs = programAttriFilters(context, programFront);
			new Thread() {
				public void run() {
					for (int i = 0; i < programFront.size(); i++) {
						boolean b = DbAdapter.getInstance(context).addProgram(
								programFront.get(i));
						if (b) {
							SLog.i(TAG, "第" + i + "个节目成功存入数据库,节目总数为："
									+ programFront.size());
						} else {
							SLog.i(TAG, "第" + i + "个节目没有成功存入数据库,节目总数为："
									+ programFront.size());
						}
					}
					SLog.i(TAG, "=================================存到db中完成");

				};
			}.start();

			// 按时间过滤后的数据
			programs = programTimeFilters(programFront);
			if (programs == null) {
				SLog.d(TAG, "过滤属性的时间的节目为空了");
			}

		}
		return programs;
	}

	/**
	 * 根据节目pid从数据库得倒节目
	 * 
	 * @param context
	 * @param pid
	 * @return
	 */
	private static ArrayList<ProgramBean> getProgramsByPid(Context context,
			String pid) {
		SLog.i(TAG, "从本地数据库判断是否有节目数据--------------------------");
		DbAdapter dbAdapter = DbAdapter.getInstance(context);
		Cursor cursor = dbAdapter.findProByChannelPid(pid);
		return getDataFromDB(cursor);
	}

	/**
	 * 根据频道id得倒数据库中的节目数据
	 * 
	 * @param context
	 * @param cid
	 * @return
	 */
	private static ArrayList<ProgramBean> getProgramsByChannelId(
			Context context, String cid) {
		SLog.i(TAG, "从本地数据库判断是否有节目数据--------------------------");
		DbAdapter dbAdapter = DbAdapter.getInstance(context);
		Cursor cursor = dbAdapter.findProByChannelId(cid);
		SLog.d(TAG, "要查的频道号是===="+cid);
		return getDataFromDB(cursor);
	}

	private static ArrayList<ProgramBean> getDataFromDB(Cursor cursor) {
		ArrayList<ProgramBean> programs = new ArrayList<ProgramBean>();
		ProgramBean program = null;
		while (cursor.moveToNext()) {
			program = new ProgramBean();
			program.setPid(cursor.getInt(cursor
					.getColumnIndex(DbAdapter.PROGRAM_PID)));
			program.setPweekday(cursor.getInt(cursor
					.getColumnIndex(DbAdapter.PROGRAM_PWEEKDAY)));
			program.setPstime(cursor.getString(cursor
					.getColumnIndex(DbAdapter.PROGRAM_PSTIME)));
			program.setPftime(cursor.getString(cursor
					.getColumnIndex(DbAdapter.PROGRAM_PFTIME)));
			program.setPn(cursor.getString(cursor
					.getColumnIndex(DbAdapter.PROGRAM_PN)));
			program.setEpgid(cursor.getInt(cursor
					.getColumnIndex(DbAdapter.PROGRAM_EPGID)));
			program.setCid(cursor.getInt(cursor
					.getColumnIndex(DbAdapter.PROGRAM_CID)));
			program.setCname(cursor.getString(cursor
					.getColumnIndex(DbAdapter.PROGRAM_CNAME)));
			program.setPtype(cursor.getString(cursor
					.getColumnIndex(DbAdapter.PROGRAM_PTYPE)));
			program.setPrecommend(cursor.getInt(cursor
					.getColumnIndex(DbAdapter.PROGRAM_PRECOMMENT)));
			program.setFid(cursor.getInt(cursor
					.getColumnIndex(DbAdapter.PROGRAM_FID)));
			program.setFid2(cursor.getInt(cursor
					.getColumnIndex(DbAdapter.PROGRAM_FID2)));

			programs.add(program);
		}
		cursor.close();
		return programs;
	}

	/**
	 * 从网络解析节目分类
	 * 
	 * @param result
	 * @return
	 */
	private static ArrayList<ProgramItemBean> paserProgramItem(
			InputStream result) {
		ArrayList<ProgramItemBean> items = null;
		ProgramItemBean fitem = null;
		XmlPullParser parser = Xml.newPullParser();

		try {
			parser.setInput(result, "UTF-8");
			int eventType = parser.getEventType();
			while (eventType != XmlPullParser.END_DOCUMENT) {

				switch (eventType) {

				case XmlPullParser.START_DOCUMENT:// 文档开始事件,可以进行数据初始化处理
					items = new ArrayList<ProgramItemBean>();
					break;
				case XmlPullParser.START_TAG:// 开始元素事件
					if ("fitem".equals(parser.getName())) {
						fitem = new ProgramItemBean();
					} else if ("epgNode".equals(parser.getName())) {
						String node = parser.nextText();
						fitem.setNode(Integer.valueOf(node));
						// SLog.d(TAG, fitem.getNode() + "");

					} else if ("epgName".equals(parser.getName())) {
						String epgName = parser.nextText();
						fitem.setName(epgName);
						// SLog.d(TAG, fitem.getName());
					} else if ("epgPNode".equals(parser.getName())) {
						String epgPNode = parser.nextText();
						fitem.setPnode(Integer.valueOf(epgPNode));
						// SLog.d(TAG, fitem.getPnode() + "");
					}

					break;
				case XmlPullParser.END_TAG:// 结束元素事件
					if ("fitem".equals(parser.getName()) && fitem != null) {
						items.add(fitem);
					}
					break;

				}
				eventType = parser.next();
			}
		} catch (Exception e) {
			SLog.d(TAG, e.toString());
			return null;
		} finally {
			try {
				if (result != null) {
					result.close();
				}
			} catch (IOException e) {
				SLog.d(TAG, e.toString());
			}
		}
		return items;
	}

	/**
	 * 从网络解析指定频道下的类表
	 * 
	 * @param result
	 */
	private static ArrayList<ProgramBean> paserProgram(InputStream result) {
		// TODO Auto-generated method stub
		XmlPullParser parser = Xml.newPullParser();
		ProgramBean pInfo = null;
		try {
			parser.setInput(result, "UTF-8");
			int eventType = parser.getEventType();
			while (eventType != XmlPullParser.END_DOCUMENT) {

				switch (eventType) {
				case XmlPullParser.START_DOCUMENT:// 文档开始事件,可以进行数据初始化处理
					programFront = new ArrayList<ProgramBean>();
					break;
				case XmlPullParser.START_TAG:// 开始元素事件
					if ("program".equals(parser.getName())) {
						pInfo = new ProgramBean();

					} else if (pInfo != null) {
						if ("pid".equals(parser.getName())) {
							String pid = parser.nextText();
							pInfo.setPid(new Integer(pid));
							// SLog.d(TAG, pInfo.getPid() + "");

						} else if ("pweekday".equals(parser.getName())) {
							String pweekday = parser.nextText();
							pInfo.setPweekday(Integer.valueOf(pweekday));
							// SLog.d(TAG, pInfo.getPweekday() + "");

						} else if ("pstime".equals(parser.getName())) {
							String pstime = parser.nextText();
							pInfo.setPstime(pstime);
							// SLog.d(TAG, pInfo.getPstime());

						} else if ("pftime".equals(parser.getName())) {
							String pftime = parser.nextText();
							pInfo.setPftime(pftime);
							// SLog.d(TAG, pInfo.getPftime());

						} else if ("pn".equals(parser.getName())) {
							String pn = parser.nextText();
							pInfo.setPn(pn);
							// SLog.d(TAG, pInfo.getPn());

						} else if ("cname".equals(parser.getName())) {
							String cname = parser.nextText();
							pInfo.setCname(cname);
							// SLog.d(TAG, "cname=" + pInfo.getCname());

						} else if ("cid".equals(parser.getName())) {
							String cid = parser.nextText();
							pInfo.setCid(Integer.valueOf(cid));
							// SLog.d(TAG, pInfo.getCid() + "");

						} else if ("epgid".equals(parser.getName())) {
							String epgid = parser.nextText();
							pInfo.setEpgid(Integer.valueOf(epgid));
							// SLog.d(TAG, pInfo.getEpgid() + "");

						} else if ("ptype".equals(parser.getName())) {
							String ptype = parser.nextText();
							pInfo.setPtype(ptype);
							// SLog.d(TAG, pInfo.getPtype() + "");
						} else if ("precommend".equals(parser.getName())) {
							String precommend = parser.nextText();
							pInfo.setPrecommend(Integer.valueOf(precommend));
							// SLog.d(TAG, pInfo.getPrecommend() + "");
						} else if ("fid".equals(parser.getName())) {
							String fid = parser.nextText();
							pInfo.setFid(Integer.valueOf(fid));
							// SLog.d(TAG, pInfo.getFid() + "");
						} else if ("fid2".equals(parser.getName())) {
							String fid2 = parser.nextText();
							pInfo.setFid2(Integer.valueOf(fid2));
							// SLog.d(TAG, pInfo.getFid2() + "");
						}
					}

					break;
				case XmlPullParser.END_TAG:// 结束元素事件
					if ("program".equals(parser.getName()) && pInfo != null) {
						programFront.add(pInfo);
					}
					break;
				}
				eventType = parser.next();
			}
		} catch (Exception e) {
			SLog.d(TAG, e.toString());
			return null;
		} finally {
			try {
				if (result != null) {
					result.close();
				}
			} catch (IOException e) {
				SLog.d(TAG, e.toString());
			}
		}
		SLog.d(TAG, "解析节目完毕，长度为，不加任何过滤：" + programFront.size());
		return programFront;

	}

	/**
	 * 用时间进行过滤
	 * 
	 * @param arrayList
	 * 
	 * @return ArrayList<ProgramBean>
	 * @throws Exception
	 */
	private static ArrayList<ProgramBean> programTimeFilters(
			ArrayList<ProgramBean> arrayList) {
		// 拿到后按时间先过滤下
		ArrayList<ProgramBean> filters_time = new ArrayList<ProgramBean>();

		SLog.d(TAG, "当前系统周数=========" + week);
		SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");

		// 得到当前系统时间，并转换成long类型
		String str = df.format(new Date());
		SLog.d(TAG, "当前系统时间========" + str);

		for (int i = 0; i < arrayList.size(); i++) {
			SLog.d(TAG, "按时间过滤的节目播放结束时间========" + arrayList.get(i).getPftime());
			SLog.d(TAG, "当前节目所在频道========" + arrayList.get(i).getCid());
			SLog.d(TAG, "当前节目的唯一标识========" + arrayList.get(i).getPid());
			SLog.d(TAG, "当前节目名称========" + arrayList.get(i).getPn());
			try {
				// 得到节目播放的开始时间,并转换成long类型
				String time = arrayList.get(i).getPstime();
				long ptime = df.parse(time).getTime();
				// 得倒节目播放的结束时间
				String ltime = arrayList.get(i).getPftime();
				long pltime = df.parse(ltime).getTime();

				// 当前时间
				long current_time = df.parse(str).getTime();
				// 得倒节目的周数
				int p_week = arrayList.get(i).getPweekday();

				// 按时间过滤方法1
				if (week == p_week && pltime > current_time) {
					filters_time.add(arrayList.get(i));
				}
				// SLog.d(TAG, "节目时间" + p_week);
				// if (week == p_week && ptime < current_time
				// && pltime > current_time) {
				// filters_time.add(arrayList.get(i));
				// }
				// // 若得到的时间小于当前时间则是没有播放过的节目，并且周数等于当前周数，则保持
				// if (week == p_week && ptime >= current_time) {
				// // SimpleDateFormat df_compare = new
				// // SimpleDateFormat("HH:mm");
				// // arrayList.get(i).setCompare_time(df_compare.format(time));
				// filters_time.add(arrayList.get(i));
				// }
			} catch (ParseException e) {
				SLog.d(TAG, e.toString());
			}
		}
		SLog.d(TAG, "按时间过滤长度：" + filters_time.size());
		return filters_time;
	}

	/**
	 * 按节目属性过滤
	 * 
	 * @param context
	 * 
	 * @param filters_time
	 * @return
	 */
	private static ArrayList<ProgramBean> programAttriFilters(Context context,
			ArrayList<ProgramBean> filters_time) {
		// 在过滤之前需要获取节目的分类把他存起来
		int[] p_item = null;
		if (getProgramItem(context).size() > 0) {
			ArrayList<ProgramItemBean> items = getProgramItem(context);
			p_item = new int[items.size()];
			for (int i = 0; i < items.size(); i++) {
				p_item[i] = items.get(i).getNode();
			}

		}

		// 按属性过滤每一个节目
		ArrayList<ProgramBean> programGrouped = new ArrayList<ProgramBean>();
		if (filters_time != null) {
			SLog.d(TAG, "我已经得倒节目不为空了");
		} else {
			SLog.d(TAG, "节目得不到了！！");
		}
		for (int i = 0; i < filters_time.size(); i++) {
			String p_type = filters_time.get(i).getPtype();
			if (!" ".contains(p_type)) {
				String[] sArray = p_type.split(",");
				// 节目属性的集合
				int[] pros = new int[sArray.length];
				for (int j = 0; j < sArray.length; j++) {
					// 测试equals，在测试==,目的把空格去掉
					if (!sArray[j].endsWith("")) {
						pros[j] = Integer.valueOf(sArray[j]);
					}
				}

				// 将节目属性和节目分类比较
				// 什么情况下将节目加入programGrouped这里？每个节目的属性和得倒的预置节目属性比较，只要相同就取
				for (int j = 0; j < pros.length; j++) {
					for (int j2 = 0; j2 < p_item.length; j2++) {
						if (pros[j] == p_item[j2]
								|| !programGrouped
										.contains(filters_time.get(i))) {
							programGrouped.add(filters_time.get(i));
						}
					}
				}

			}
		}
		return programGrouped;

	}
}